﻿using ChessGame.Movement;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ChessGame
{
    /// <summary>
    /// Chess object extended from form
    /// </summary>
    public partial class Chess : Form
    {
        public Game game;
        public static List<PanelView> panelList;
        public List<MovementOption> previousListMovementOptions;
        public List<HitOption> previousListHitOptions;
        public int lastCoordinaatX;
        public int lastCoordinaatY;
        private int players;

        /// <summary>
        /// Chess constructor
        /// </summary>
        public Chess()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Chess constructor
        /// </summary>
        /// <param name="_players">The amount of players</param>
        public Chess(int _players)
        {
            this.players = _players;
            InitializeComponent();
        }

        /// <summary>
        /// Load function 
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">EventArgs</param>
        private void Form1_Load(object sender, EventArgs e)
        {
            game = new Game(this);
            this.FormClosed += Chess_FormClosed;
            var black = Color.DarkGray;
            var white = Color.White;
            panelList = new List<PanelView>();
            previousListMovementOptions = new List<MovementOption>();
            previousListHitOptions = new List<HitOption>();
            lastCoordinaatX = 0;
            lastCoordinaatY = 0;
            #region Panel Row 1
            panelA1.BackColor = black;
            panelB1.BackColor = white;
            panelC1.BackColor = black;
            panelD1.BackColor = white;
            panelE1.BackColor = black;
            panelF1.BackColor = white;
            panelG1.BackColor = black;
            panelH1.BackColor = white;

            panelA1.Click += Panel_Click;
            panelB1.Click += Panel_Click;
            panelC1.Click += Panel_Click;
            panelD1.Click += Panel_Click;
            panelE1.Click += Panel_Click;
            panelF1.Click += Panel_Click;
            panelG1.Click += Panel_Click;
            panelH1.Click += Panel_Click;

            panelList.Add(new PanelView(panelA1, "A1"));
            panelList.Add(new PanelView(panelB1, "B1"));
            panelList.Add(new PanelView(panelC1, "C1"));
            panelList.Add(new PanelView(panelD1, "D1"));
            panelList.Add(new PanelView(panelE1, "E1"));
            panelList.Add(new PanelView(panelF1, "F1"));
            panelList.Add(new PanelView(panelG1, "G1"));
            panelList.Add(new PanelView(panelH1, "H1"));
            #endregion

            #region Panel Row 2
            panelA2.BackColor = white;
            panelB2.BackColor = black;
            panelC2.BackColor = white;
            panelD2.BackColor = black;
            panelE2.BackColor = white;
            panelF2.BackColor = black;
            panelG2.BackColor = white;
            panelH2.BackColor = black;

            panelA2.Click += Panel_Click;
            panelB2.Click += Panel_Click;
            panelC2.Click += Panel_Click;
            panelD2.Click += Panel_Click;
            panelE2.Click += Panel_Click;
            panelF2.Click += Panel_Click;
            panelG2.Click += Panel_Click;
            panelH2.Click += Panel_Click;

            panelList.Add(new PanelView(panelA2, "A2"));
            panelList.Add(new PanelView(panelB2, "B2"));
            panelList.Add(new PanelView(panelC2, "C2"));
            panelList.Add(new PanelView(panelD2, "D2"));
            panelList.Add(new PanelView(panelE2, "E2"));
            panelList.Add(new PanelView(panelF2, "F2"));
            panelList.Add(new PanelView(panelG2, "G2"));
            panelList.Add(new PanelView(panelH2, "H2"));
            #endregion

            #region Panel Row 3
            panelA3.BackColor = black;
            panelB3.BackColor = white;
            panelC3.BackColor = black;
            panelD3.BackColor = white;
            panelE3.BackColor = black;
            panelF3.BackColor = white;
            panelG3.BackColor = black;
            panelH3.BackColor = white;

            panelA3.Click += Panel_Click;
            panelB3.Click += Panel_Click;
            panelC3.Click += Panel_Click;
            panelD3.Click += Panel_Click;
            panelE3.Click += Panel_Click;
            panelF3.Click += Panel_Click;
            panelG3.Click += Panel_Click;
            panelH3.Click += Panel_Click;

            panelList.Add(new PanelView(panelA3, "A3"));
            panelList.Add(new PanelView(panelB3, "B3"));
            panelList.Add(new PanelView(panelC3, "C3"));
            panelList.Add(new PanelView(panelD3, "D3"));
            panelList.Add(new PanelView(panelE3, "E3"));
            panelList.Add(new PanelView(panelF3, "F3"));
            panelList.Add(new PanelView(panelG3, "G3"));
            panelList.Add(new PanelView(panelH3, "H3"));
            #endregion

            #region Panel Row 4
            panelA4.BackColor = white;
            panelB4.BackColor = black;
            panelC4.BackColor = white;
            panelD4.BackColor = black;
            panelE4.BackColor = white;
            panelF4.BackColor = black;
            panelG4.BackColor = white;
            panelH4.BackColor = black;

            panelA4.Click += Panel_Click;
            panelB4.Click += Panel_Click;
            panelC4.Click += Panel_Click;
            panelD4.Click += Panel_Click;
            panelE4.Click += Panel_Click;
            panelF4.Click += Panel_Click;
            panelG4.Click += Panel_Click;
            panelH4.Click += Panel_Click;

            panelList.Add(new PanelView(panelA4, "A4"));
            panelList.Add(new PanelView(panelB4, "B4"));
            panelList.Add(new PanelView(panelC4, "C4"));
            panelList.Add(new PanelView(panelD4, "D4"));
            panelList.Add(new PanelView(panelE4, "E4"));
            panelList.Add(new PanelView(panelF4, "F4"));
            panelList.Add(new PanelView(panelG4, "G4"));
            panelList.Add(new PanelView(panelH4, "H4"));
            #endregion

            #region Panel Row 5
            panelA5.BackColor = black;
            panelB5.BackColor = white;
            panelC5.BackColor = black;
            panelD5.BackColor = white;
            panelE5.BackColor = black;
            panelF5.BackColor = white;
            panelG5.BackColor = black;
            panelH5.BackColor = white;

            panelA5.Click += Panel_Click;
            panelB5.Click += Panel_Click;
            panelC5.Click += Panel_Click;
            panelD5.Click += Panel_Click;
            panelE5.Click += Panel_Click;
            panelF5.Click += Panel_Click;
            panelG5.Click += Panel_Click;
            panelH5.Click += Panel_Click;

            panelList.Add(new PanelView(panelA5, "A5"));
            panelList.Add(new PanelView(panelB5, "B5"));
            panelList.Add(new PanelView(panelC5, "C5"));
            panelList.Add(new PanelView(panelD5, "D5"));
            panelList.Add(new PanelView(panelE5, "E5"));
            panelList.Add(new PanelView(panelF5, "F5"));
            panelList.Add(new PanelView(panelG5, "G5"));
            panelList.Add(new PanelView(panelH5, "H5"));
            #endregion

            #region Panel Row 6
            panelA6.BackColor = white;
            panelB6.BackColor = black;
            panelC6.BackColor = white;
            panelD6.BackColor = black;
            panelE6.BackColor = white;
            panelF6.BackColor = black;
            panelG6.BackColor = white;
            panelH6.BackColor = black;

            panelA6.Click += Panel_Click;
            panelB6.Click += Panel_Click;
            panelC6.Click += Panel_Click;
            panelD6.Click += Panel_Click;
            panelE6.Click += Panel_Click;
            panelF6.Click += Panel_Click;
            panelG6.Click += Panel_Click;
            panelH6.Click += Panel_Click;

            panelList.Add(new PanelView(panelA6, "A6"));
            panelList.Add(new PanelView(panelB6, "B6"));
            panelList.Add(new PanelView(panelC6, "C6"));
            panelList.Add(new PanelView(panelD6, "D6"));
            panelList.Add(new PanelView(panelE6, "E6"));
            panelList.Add(new PanelView(panelF6, "F6"));
            panelList.Add(new PanelView(panelG6, "G6"));
            panelList.Add(new PanelView(panelH6, "H6"));
            #endregion

            #region Panel Row 7
            panelA7.BackColor = black;
            panelB7.BackColor = white;
            panelC7.BackColor = black;
            panelD7.BackColor = white;
            panelE7.BackColor = black;
            panelF7.BackColor = white;
            panelG7.BackColor = black;
            panelH7.BackColor = white;

            panelA7.Click += Panel_Click;
            panelB7.Click += Panel_Click;
            panelC7.Click += Panel_Click;
            panelD7.Click += Panel_Click;
            panelE7.Click += Panel_Click;
            panelF7.Click += Panel_Click;
            panelG7.Click += Panel_Click;
            panelH7.Click += Panel_Click;

            panelList.Add(new PanelView(panelA7, "A7"));
            panelList.Add(new PanelView(panelB7, "B7"));
            panelList.Add(new PanelView(panelC7, "C7"));
            panelList.Add(new PanelView(panelD7, "D7"));
            panelList.Add(new PanelView(panelE7, "E7"));
            panelList.Add(new PanelView(panelF7, "F7"));
            panelList.Add(new PanelView(panelG7, "G7"));
            panelList.Add(new PanelView(panelH7, "H7"));
            #endregion

            #region Panel Row 8
            panelA8.BackColor = white;
            panelB8.BackColor = black;
            panelC8.BackColor = white;
            panelD8.BackColor = black;
            panelE8.BackColor = white;
            panelF8.BackColor = black;
            panelG8.BackColor = white;
            panelH8.BackColor = black;

            panelA8.Click += Panel_Click;
            panelB8.Click += Panel_Click;
            panelC8.Click += Panel_Click;
            panelD8.Click += Panel_Click;
            panelE8.Click += Panel_Click;
            panelF8.Click += Panel_Click;
            panelG8.Click += Panel_Click;
            panelH8.Click += Panel_Click;

            panelList.Add(new PanelView(panelA8, "A8"));
            panelList.Add(new PanelView(panelB8, "B8"));
            panelList.Add(new PanelView(panelC8, "C8"));
            panelList.Add(new PanelView(panelD8, "D8"));
            panelList.Add(new PanelView(panelE8, "E8"));
            panelList.Add(new PanelView(panelF8, "F8"));
            panelList.Add(new PanelView(panelG8, "G8"));
            panelList.Add(new PanelView(panelH8, "H8"));
            #endregion

            game.Start();
            TurnLabel.Text = game.Turn;

        }

        void Chess_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Dispose();
            Application.Run(new Controller());
        }

        /// <summary>
        /// Event when panel is clicked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">EventArgs</param>
        private void Panel_Click(object sender, EventArgs e)
        {
            ClearBackground();
            Panel panel = (Panel)sender;
            List<MovementOption> listMovementOptions;
            List<HitOption> listHitOptions;
            Boolean move = false;
            Boolean kill = false;
            Boolean chekmate = false;
            int coordinaatX = StringToNumber(panel.Name.Substring(5, 1));
            int coordinaatY = Convert.ToInt32(panel.Name.Substring(6, 1));

            foreach (MovementOption movementOption in previousListMovementOptions)
            {
                if (((lastCoordinaatX + movementOption.X) == coordinaatX) && ((lastCoordinaatY + movementOption.Y) == coordinaatY)) { move = true; }
            }
            foreach (HitOption hitOption in previousListHitOptions)
            {
                if (((lastCoordinaatX + hitOption.X) == coordinaatX) && ((lastCoordinaatY + hitOption.Y) == coordinaatY)) { kill = true; }
            }

            if (kill || move)
            {
                CheckMateLabel.Enabled = false;
                CheckLabel.Enabled = false;
                /// Game kill command
                if (kill)
                {
                    game.Kill(coordinaatX, coordinaatY);
                    game.Move(lastCoordinaatX, lastCoordinaatY, coordinaatX, coordinaatY);
                }
                /// Game move command
                else if (move)
                {
                    CheckMateLabel.Enabled = false;
                    CheckLabel.Enabled = false;

                    game.Move(lastCoordinaatX, lastCoordinaatY, coordinaatX, coordinaatY);
                }

                previousListMovementOptions.Clear();
                previousListHitOptions.Clear();
                TurnLabel.Text = game.Turn;
                /// Game Check or Checkmate
                if (game.CheckIfCheck(game.Turn))
                {
                    CheckLabel.Enabled = true;
                    if (game.CheckIfCheckMate(game.Turn))
                    {
                        chekmate = true;
                        CheckMateLabel.Enabled = true;
                        ClearBoard();
                        game.Stop();
                        TurnLabel.Text = "";
                        ClearBackground();
                    }
                }
                // Artificial intelligence
                if (players == 1 && !chekmate)
                {
                    //game.RandomComputerMove();
                    ClearBackground();
                    game.CalculatedMove();
                    
                }
            }
            else
            {
                if (game.CheckOwnSideForPiece(coordinaatX, coordinaatY))
                {
                    // Show the piece in Blue if it's on the panel
                    panel.BackColor = Color.Blue;
                    try
                    {
                        listMovementOptions = game.GetMovementPossibilities(coordinaatX, coordinaatY);
                        listHitOptions = game.GetHitPossiblities(coordinaatX, coordinaatY);
                        foreach (MovementOption movementOption in listMovementOptions)
                        {
                            Panel panelOption = GetPanel(NumberToString((coordinaatX + movementOption.X)) + "" + (coordinaatY + movementOption.Y));
                            panelOption.BackColor = Color.LightBlue;
                        }
                        foreach (HitOption hitOption in listHitOptions)
                        {
                            Panel panelOption = GetPanel(NumberToString((coordinaatX + hitOption.X)) + "" + (coordinaatY + hitOption.Y));
                            panelOption.BackColor = Color.Red;
                        }
                        previousListMovementOptions = listMovementOptions;
                        previousListHitOptions = listHitOptions;
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.Message);
                    }
                }
            }
            lastCoordinaatX = coordinaatX;
            lastCoordinaatY = coordinaatY;

        }

        /// <summary>
        /// Click Event of StartButton
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">EventArgs</param>
        private void StartButton_Click(object sender, EventArgs e)
        {
            game.Start();
            TurnLabel.Text = game.Turn;

        }

        /// <summary>
        /// Click Event of StopButton
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">EventArgs</param>
        private void StopButton_Click(object sender, EventArgs e)
        {
            ClearBoard();
            game.Stop();
            TurnLabel.Text = "";
            //if (lastPanel != null)
            //{
            //    lastPanel.BackColor = lastColor;
            //}
            ClearBackground();
        }

        /// <summary>
        /// Clear's the board Panel
        /// </summary>
        private void ClearBoard()
        {
            foreach (PanelView panelView in panelList)
            {
                panelView.panel.BackgroundImage = null;
            }

        }

        /// <summary>
        /// Clear's the background colour's of the panel's
        /// </summary>
        private void ClearBackground()
        {
            var black = Color.DarkGray;
            var white = Color.White;

            #region Panel Row 1
            panelA1.BackColor = black;
            panelB1.BackColor = white;
            panelC1.BackColor = black;
            panelD1.BackColor = white;
            panelE1.BackColor = black;
            panelF1.BackColor = white;
            panelG1.BackColor = black;
            panelH1.BackColor = white;
            #endregion

            #region Panel Row 2
            panelA2.BackColor = white;
            panelB2.BackColor = black;
            panelC2.BackColor = white;
            panelD2.BackColor = black;
            panelE2.BackColor = white;
            panelF2.BackColor = black;
            panelG2.BackColor = white;
            panelH2.BackColor = black;
            #endregion

            #region Panel Row 3
            panelA3.BackColor = black;
            panelB3.BackColor = white;
            panelC3.BackColor = black;
            panelD3.BackColor = white;
            panelE3.BackColor = black;
            panelF3.BackColor = white;
            panelG3.BackColor = black;
            panelH3.BackColor = white;
            #endregion

            #region Panel Row 4
            panelA4.BackColor = white;
            panelB4.BackColor = black;
            panelC4.BackColor = white;
            panelD4.BackColor = black;
            panelE4.BackColor = white;
            panelF4.BackColor = black;
            panelG4.BackColor = white;
            panelH4.BackColor = black;
            #endregion

            #region Panel Row 5
            panelA5.BackColor = black;
            panelB5.BackColor = white;
            panelC5.BackColor = black;
            panelD5.BackColor = white;
            panelE5.BackColor = black;
            panelF5.BackColor = white;
            panelG5.BackColor = black;
            panelH5.BackColor = white;
            #endregion

            #region Panel Row 6
            panelA6.BackColor = white;
            panelB6.BackColor = black;
            panelC6.BackColor = white;
            panelD6.BackColor = black;
            panelE6.BackColor = white;
            panelF6.BackColor = black;
            panelG6.BackColor = white;
            panelH6.BackColor = black;
            #endregion

            #region Panel Row 7
            panelA7.BackColor = black;
            panelB7.BackColor = white;
            panelC7.BackColor = black;
            panelD7.BackColor = white;
            panelE7.BackColor = black;
            panelF7.BackColor = white;
            panelG7.BackColor = black;
            panelH7.BackColor = white;
            #endregion

            #region Panel Row 8
            panelA8.BackColor = white;
            panelB8.BackColor = black;
            panelC8.BackColor = white;
            panelD8.BackColor = black;
            panelE8.BackColor = white;
            panelF8.BackColor = black;
            panelG8.BackColor = white;
            panelH8.BackColor = black;

            #endregion
        }

        /// <summary>
        /// Set Image on certain panel place
        /// </summary>
        /// <param name="colour">Chesspiece colour</param>
        /// <param name="type">Chesspiece type</param>
        /// <param name="place">Chesspiece place</param>
        public void SetImage(string colour, string type, string place)
        {
            if (InvokeRequired)
            {
                try
                {
                    this.Invoke((Action<string, string, string>)SetImage, new object[] { colour, type, place });
                    return;
                }
                catch (Exception e)
                {

                    Console.WriteLine(e.Message);
                }
            }
            try
            {
                List<PanelView> list = panelList.Where(c => c.name == place).ToList();
                foreach (PanelView panelView in list)
                {
                    panelView.panel.BackgroundImage = Image.GetPieceImage(colour, type);
                }
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Clear a Image
        /// </summary>
        /// <param name="colour">Chesspiece colour</param>
        /// <param name="type">Chesspiece type</param>
        /// <param name="place">Chesspiece place</param>
        public void ClearImage(string colour, string type, string place)
        {
            if (InvokeRequired)
            {
                try
                {
                    this.Invoke((Action<string, string, string>)ClearImage, new object[] { colour, type, place });
                    return;
                }
                catch (Exception e)
                {

                    Console.WriteLine(e.Message);
                }
            }
            try
            {
                List<PanelView> list = panelList.Where(c => c.name == place).ToList();
                foreach (PanelView panelView in list)
                {
                    panelView.panel.BackgroundImage = new Bitmap(50, 50); ;
                }
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Hit another colour
        /// </summary>
        /// <param name="x">Position X</param>
        /// <param name="y">Position Y</param>
        public void Hit(int x, int y)
        {
            if (InvokeRequired)
            {
                try
                {
                    this.Invoke((Action<int, int>)Hit, new object[] { x, y });
                    return;
                }
                catch (Exception e)
                {

                    Console.WriteLine(e.Message);
                }
            }
            try
            {
                string place = NumberToString(x) + "" + y.ToString();
                List<PanelView> list = panelList.Where(c => c.name == place).ToList();
                foreach (PanelView panelView in list)
                {
                    panelView.panel.BackColor = Color.Red;
                }
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Get Panel by PanelID
        /// </summary>
        /// <param name="panelID">PanelID</param>
        /// <returns></returns>
        private Panel GetPanel(string panelID)
        {
            List<PanelView> list = panelList.Where(c => c.name == panelID).ToList();
            return list[0].panel;
        }

        /// <summary>
        /// String to Number
        /// </summary>
        /// <param name="value">String</param>
        /// <returns>Number</returns>
        private int StringToNumber(string value)
        {
            switch (value)
            {
                case "A":
                    return 1;
                case "B":
                    return 2;
                case "C":
                    return 3;
                case "D":
                    return 4;
                case "E":
                    return 5;
                case "F":
                    return 6;
                case "G":
                    return 7;
                case "H":
                    return 8;
                default:
                    return 0;
            }
        }

        /// <summary>
        /// Number to String
        /// </summary>
        /// <param name="number">Number</param>
        /// <returns>String</returns>
        private string NumberToString(int number)
        {
            switch (number)
            {
                case 1:
                    return "A";
                case 2:
                    return "B";
                case 3:
                    return "C";
                case 4:
                    return "D";
                case 5:
                    return "E";
                case 6:
                    return "F";
                case 7:
                    return "G";
                case 8:
                    return "H";
                default:
                    return "";
            }
        }

        /// <summary>
        /// Click Event for ChangeColour button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ChangeColour_Click(object sender, EventArgs e)
        {
            game.NextTurn();
            TurnLabel.Text = "Black";
        }

        private void CheckLabel_Click(object sender, EventArgs e)
        {

        }

        private void panelH7_Paint(object sender, PaintEventArgs e)
        {

        }

        private void CheckMateLabel_Click(object sender, EventArgs e)
        {

        }

        private void panelH6_Paint(object sender, PaintEventArgs e)
        {

        }

        public void ChangeSetColour(int fromX, int fromY, int toX, int toY)
        {
            Panel panelOption = GetPanel(NumberToString(fromX) +""+ fromY);
            panelOption.BackColor = Color.Wheat;
            Panel panelOptioner = GetPanel(NumberToString(toX) + "" +toY);
            panelOptioner.BackColor = Color.SandyBrown;
        }
    }
}
